/*
 * Copyright (c) 2017 Fingerprint Cards AB <tech@fingerprints.com>
 *
 * All rights are reserved.
 * Proprietary and confidential.
 * Unauthorized copying of this file, via any medium is strictly prohibited.
 * Any use is subject to an appropriate license granted by Fingerprint Cards AB.
 */

#ifndef FPC_BEP_BIO_H
#define FPC_BEP_BIO_H

/**
 * @file    fpc_bep_bio.h
 * @brief   Biometric API
 *
 * This is the biometric API of the Biometric Embedded Platform (BEP) library.
 * The library contains functionality for use with biometric hardware from
 * Fingerprint Cards. It is targeting embedded systems with tight
 * restrictions on available CPU, memory and storage resources.
 *
 * The library is by definition executing in the same security domain as the
 * caller, therefore the API does not define any security mechanisms and it is
 * the responsibility of the caller to securely deliver and protect any
 * sensitive data being delivered to other parts of the system.
 *
 * @note This is a work-in-progress specification. Implementers are informed
 * that this API may change without providing any backward compatibility.
 * However it is FPC's ambition that the API shall remain compatible between
 * releases.
 */

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

#include "fpc_bep_types.h"
#include "fpc_bep_algorithm.h"
#include "fpc_bep_bio_param.h"

/**
 * @brief Manage RAM buffer containing serialized template data in BEP library.
 */
typedef enum {
    /** Disable memory release in BEP library */
    FPC_BEP_DISABLE_MEM_RELEASE = 0,
    /** Enable memory release in BEP library */
    FPC_BEP_ENABLE_MEM_RELEASE  = 1
} fpc_bep_mem_release_t;

/**
 * @brief Enrollment status feedback.
 */
typedef enum {
    /** Enrollment is done. */
    FPC_BEP_ENROLLMENT_DONE = 1,
    /** Enrollment made progress. */
    FPC_BEP_ENROLLMENT_PROGRESS = 2,
    /** Enrollment rejected because of low quality. */
    FPC_BEP_ENROLLMENT_REJECT_REASON_LOW_QUALITY = 3,
    /** Enrollment rejected because of low sensor coverage. */
    FPC_BEP_ENROLLMENT_REJECT_REASON_LOW_SENSOR_COVERAGE = 4,
    /** Enrollment rejected because of unknown reason. */
    FPC_BEP_ENROLLMENT_REJECT_REASON_OTHER = 5,
} fpc_bep_enrollment_feedback_t;

/**
 * @brief Enrollment status indicating the progress of an ongoing enrollment.
 *
 * The samples remaining field indicates the progress in a multi-touch
 * enrollment.
 */
typedef struct {
    /** Number of samples remaining until enrollment is completed. */
    uint32_t samples_remaining;
    /** Enrollment status feedback. */
    fpc_bep_enrollment_feedback_t feedback;
} fpc_bep_enrollment_status_t;

/**
 * @brief Biometric fingerprint template.
 */
typedef struct fpc_bep_template fpc_bep_template_t;

/**
 * @brief Identify result details.
 */
typedef struct {
    /**
     * Identify match result. True if the extracted identify template
     * matches any of the candidates, false otherwise.
     */
    bool match;
    /**
     * The index of the template in candidates that matched the identify template.
     * Only valid if match is true.
     */
    size_t index;
} fpc_bep_identify_result_t;

/**
 * @brief Gets recommended configuration parameters for the FPC BEP library.
 *
 * Recommended configuration parameters are determined based on specified sensor and algorithm.
 * This function could be called before the BEP library is initialized.
 *
 * @param[in] algorithm Algorithm configuration.
 * @param[out] param The recommended BEP library configuration parameters.
 *
 * @return ::fpc_bep_result_t
 */
fpc_bep_result_t fpc_bep_bio_get_recommended_param(const fpc_bep_algorithm_t *algorithm,
                                                   fpc_bep_bio_param_t *param);

/**
 * @brief Initializes the biometric part of FPC BEP library.
 *
 * Requires that the sensor is already initialized, see fpc_bep_sensor_init().
 * This function must be called before using functionality of the fpc_bep_bio.h.
 * Only fpc_bep_get_recommended_param() and fpc_bep_get_max_template_size()
 * could be called before fpc_bep_bio_init().
 *
 * @param[in] param BEP library configuration parameters.
 * @param[in] algorithm BEP library algorithm to be initialized.
 *
 * @return ::fpc_bep_result_t
 */
fpc_bep_result_t fpc_bep_bio_init(fpc_bep_bio_param_t *param,
                                  const fpc_bep_algorithm_t *algorithm);

/**
 * @brief Releases the biometric part of FPC BEP library.
 *
 * After the biometric resources successfully has been released a new
 * initialization must be performed by calling fpc_bep_bio_init().
 *
 * @return ::fpc_bep_result_t
 */
fpc_bep_result_t fpc_bep_bio_release(void);

/**
 * @brief Extracts features from an image.
 *
 * Extracts features from an image and stores the features in a template.
 * The resulting template is intended for matching against existing enrolled
 * template(s).
 *
 * This function supports image extraction for both internal template matching and
 * external template matching e.g. matching in Secure Element.
 * For internal template matching the template pointer could be set to NULL,
 * the template will be kept in BEP library context until released by calling
 * fpc_bep_identify_release().
 *
 * @param[in] image Image from which features are extracted. Image will be released by call.
 * This is due to RAM optimization.
 * @param[out] template Template with features. Set to NULL for internal identify.
 * The caller is responsible for deleting the template.
 * @return ::fpc_bep_result_t
 */
fpc_bep_result_t fpc_bep_image_extract(fpc_bep_image_t **image, fpc_bep_template_t **template);

/**
 * @brief Gets the size of template data in serialized form.
 *
 * @param[in] template The template.
 * @param[out] size Size of serialized template data [byte].
 * @return ::fpc_bep_result_t
 */
fpc_bep_result_t fpc_bep_template_get_size(const fpc_bep_template_t *template, size_t *size);

/**
 * @brief Serializes a template to a data buffer.
 *
 * Serializes a template to a data buffer as an array of consecutive bytes, in
 * a format suitable for storage and transmission. The serialized format is
 * dependent on selected match location from fpc_bep_bio_init().
 *
 * The caller is responsible for allocating the data buffer. If the size of the
 * buffer is not large enough to fit the complete template data, the template
 * will be truncated in a controlled way. The full size of the template data
 * can be retrieved using fpc_bep_template_get_size().
 *
 * @param[in] template The template.
 * @param[in,out] data The template data buffer.
 * @param[in] data_size The size of the template data buffer.
 * @return ::fpc_bep_result_t
 */
fpc_bep_result_t fpc_bep_template_serialize(
    const fpc_bep_template_t *template, uint8_t *data, size_t data_size);

/**
 * @brief Deserializes a template from a data buffer.
 *
 * The template data buffer shall contain a template in the format as created
 * by fpc_bep_template_serialize().
 *
 * The template data must remain valid throughout the existence of the template object,
 * which is until calling fpc_bep_template_delete(). The \p data_release parameter could
 * be used to let the BEP library handle memory release of the data buffer.
 * Template data stored in memory mapped non-volatile memory is supported by setting
 * \p data_release to FPC_BEP_DISABLE_MEM_RELEASE.
 *
 * @param[out] template The template.
 * @param[in] data The template data buffer.
 * @param[in] data_size The size of the template data buffer.
 * @param[in] data_release Controls if the provided #data should be released by the BEP library.
 * @return ::fpc_bep_result_t
 */
fpc_bep_result_t fpc_bep_template_deserialize(fpc_bep_template_t **template, uint8_t *data,
        size_t data_size, fpc_bep_mem_release_t data_release);

/**
 * @brief Releases the provided template and the resources associated with it.
 *
 * @param[in] template The template to release. If NULL, no operation is
 * performed. Template pointer set to NULL when released.
 * @return ::fpc_bep_result_t
 */
fpc_bep_result_t fpc_bep_template_delete(fpc_bep_template_t **template);

/**
 * @brief Identify extracted template by matching it against the specified candidates.
 *
 * This function will perform template to template matching. If a match is found,
 * the index of the matching template will be returned.
 * This function could be called multiple times by provide a sub-set of the available
 * candidates at a time.
 *
 * @note The source template is provided by calling ::fpc_bep_image_extract().
 * This function can be used to perform a verification (1:1 match) by supplying only one candidate.
 *
 * @param[in] candidates The candidate templates to match against.
 * @param[in] candidates_count Number of entries in candidates.
 * @param[out] result Identify result details.
 * @return ::fpc_bep_result_t
 */
fpc_bep_result_t fpc_bep_identify(const fpc_bep_template_t **candidates,
        const size_t candidates_count, fpc_bep_identify_result_t *result);

/**
 * @brief  Releases the identify session and gets the template update status.
 *
 * This function releases the identify session and informs if the
 * the template should be updated or not. It must always be called
 * after calling ::fpc_bep_identify().
 *
 * @param[out] update_template True if the template that matched the image
 * needs to be updated, false otherwise.
 * @return ::fpc_bep_result_t
 */
fpc_bep_result_t fpc_bep_identify_release(bool *update_template);

/**
 * @brief Starts an enrollment session.
 *
 * This function will start enrollment of a new template. Images
 * should then be added to the enrollment session using fpc_bep_enroll().
 * When that function indicates that the enrollment is completed,
 * fpc_bep_enroll_finish() should be called to finish the session and obtain
 * the id of the enrolled template.
 *
 * Note that there can only be one ongoing enrollment session at a time. So
 * once an enrollment session has been started using fpc_bep_enroll_start()
 * it must be finished by calling fpc_bep_enroll_finish() before a new session
 * can be started.
 *
 * @return ::fpc_bep_result_t
 */
fpc_bep_result_t fpc_bep_enroll_start(void);

/**
 * @brief Finishes an enrollment session.
 *
 * This function releases all resources associated with the enrollment
 * session.
 *
 * In case the enrollment was successfully completed, the enrolled template
 * will be returned through the template argument.
 *
 * An ongoing enrollment session can be cancelled by calling this function
 * before the status returned from fpc_bep_enroll() indicates that the
 * Enrollment is complete. In that case fpc_bep_enroll_finish() will return
 * FPC_BEP_RESULT_CANCELLED. The template pointer is allowed to be NULL.
 *
 * @param[out] template The enrolled template. The caller is responsible
 * for deleting the template. Could be set to NULL in case of cancel the
 * enrollment session.
 * @return ::fpc_bep_result_t
 */
fpc_bep_result_t fpc_bep_enroll_finish(fpc_bep_template_t **template);

/**
 * @brief Adds an image to an ongoing enrollment session.
 *
 * The status will be set to indicate the progress and signal any potential
 * user feedback regarding the provided image. The enrollment is complete when
 * the status indicates that no more samples are required. The session should
 * then be finished by calling fpc_bep_enroll_finish().
 *
 * @param[in] image Image from which features are extracted. Image will be
 * released by call. This is due to RAM optimization.
 * @param[out] status Status of the operation.
 * @return ::fpc_bep_result_t
 */
fpc_bep_result_t fpc_bep_enroll(fpc_bep_image_t **image, fpc_bep_enrollment_status_t *status);

/**
 * @brief Gets the size of the latest enrolled subtemplate in serialized form.
 *
 * @param[out] size Size of serialized enroll subtemplate [byte].
 * @return ::fpc_bep_result_t
 */
fpc_bep_result_t fpc_bep_enroll_subtemplate_get_size(size_t *size);

/**
 * @brief Serializes the latest enrolled subtemplate to a data buffer.
 *
 * Serializes the latest enrolled subtemplate to a data buffer as an array
 * of consecutive bytes, in a format suitable for storage.
 *
 * The caller is responsible for allocating the data buffer. The size of the
 * template data can be retrieved using fpc_bep_enroll_subtemplate_get_size().
 *
 * @param[in,out] data The subtemplate data buffer.
 * @param[in] data_size The size of the subtemplate data buffer.
 * @return ::fpc_bep_result_t
 */
fpc_bep_result_t fpc_bep_enroll_subtemplate_serialize(uint8_t *data, size_t data_size);

/**
 * @brief Deserializes enrolled subtemplates from a data buffer to a just started enroll session.
 *
 * The subtemplate data buffer shall contain subtemplates in the format as created
 * by fpc_bep_enroll_subtemplate_serialize(). The subtemplates shall be placed consecutively
 * in the data buffer, starting with the first enroll subtemplate, then the second and so on.
 *
 * @param[in] data The subtemplate data buffer.
 * @param[in] data_size The size of the subtemplate data buffer.
 * @return ::fpc_bep_result_t
 */
fpc_bep_result_t fpc_bep_enroll_subtemplates_deserialize(uint8_t *data, size_t data_size);
#endif /* FPC_BEP_BIO_H */
